package com.insight.service;

import com.insight.entity.MetadataColumn;
import com.insight.entity.MetadataTable;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

/**
 * T104: MetadataCacheService实现
 * 元数据缓存服务,使用Spring Cache抽象提供缓存功能
 *
 * 功能特性:
 * 1. 缓存穿透防护 - 参数校验,缓存空结果
 * 2. 缓存雪崩防护 - TTL随机化(通过Redis配置)
 * 3. 缓存失效管理 - 提供缓存清除方法
 * 4. 统一缓存策略 - 使用Spring Cache注解
 *
 * 缓存策略:
 * - metadataSearch: 搜索结果缓存(TTL: 5分钟)
 * - metadataQuery: 查询结果缓存(TTL: 10分钟)
 *
 * @author Insight Team
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MetadataCacheService {

    private final MetadataSearchService searchService;
    private final MetadataQueryService queryService;

    // ==================== 搜索方法 (缓存) ====================

    /**
     * 根据表名搜索表元数据 (带缓存)
     * 缓存穿透防护: null和空字符串直接返回空结果
     *
     * @param keyword  搜索关键词
     * @param pageable 分页参数
     * @return 表元数据分页结果
     */
    @Cacheable(value = "metadataSearch", key = "'table:name:' + #keyword + ':' + #pageable.pageNumber + ':' + #pageable.pageSize",
            unless = "#result == null")
    public Page<MetadataTable> searchTablesByName(String keyword, Pageable pageable) {
        // 缓存穿透防护: 校验参数
        if (!StringUtils.hasText(keyword)) {
            log.debug("Empty keyword for table name search, returning empty page");
            return Page.empty(pageable);
        }

        log.debug("Cache miss for table name search: keyword={}", keyword);
        return searchService.searchTablesByName(keyword, pageable);
    }

    /**
     * 全文搜索表元数据 (带缓存)
     * 使用BM25算法进行相关性排序
     *
     * @param keyword  搜索关键词
     * @param pageable 分页参数
     * @return 表元数据分页结果
     */
    @Cacheable(value = "metadataSearch", key = "'table:fulltext:' + #keyword + ':' + #pageable.pageNumber + ':' + #pageable.pageSize",
            unless = "#result == null")
    public Page<MetadataTable> searchTablesByFullText(String keyword, Pageable pageable) {
        // 缓存穿透防护: 校验参数
        if (!StringUtils.hasText(keyword)) {
            log.debug("Empty keyword for full-text search, returning empty page");
            return Page.empty(pageable);
        }

        log.debug("Cache miss for full-text table search: keyword={}", keyword);
        return searchService.searchTablesByFullText(keyword, pageable);
    }

    /**
     * 根据列名搜索列元数据 (带缓存)
     *
     * @param keyword  搜索关键词
     * @param pageable 分页参数
     * @return 列元数据分页结果
     */
    @Cacheable(value = "metadataSearch", key = "'column:name:' + #keyword + ':' + #pageable.pageNumber + ':' + #pageable.pageSize",
            unless = "#result == null")
    public Page<MetadataColumn> searchColumnsByName(String keyword, Pageable pageable) {
        // 缓存穿透防护: 校验参数
        if (!StringUtils.hasText(keyword)) {
            log.debug("Empty keyword for column name search, returning empty page");
            return Page.empty(pageable);
        }

        log.debug("Cache miss for column name search: keyword={}", keyword);
        return searchService.searchColumnsByName(keyword, pageable);
    }

    /**
     * 根据数据类型筛选列元数据 (带缓存)
     *
     * @param dataType 数据类型
     * @param pageable 分页参数
     * @return 列元数据分页结果
     */
    @Cacheable(value = "metadataSearch", key = "'column:datatype:' + #dataType + ':' + #pageable.pageNumber + ':' + #pageable.pageSize",
            unless = "#result == null")
    public Page<MetadataColumn> searchColumnsByDataType(String dataType, Pageable pageable) {
        // 缓存穿透防护: 校验参数
        if (!StringUtils.hasText(dataType)) {
            log.debug("Empty data type for column search, returning empty page");
            return Page.empty(pageable);
        }

        log.debug("Cache miss for column data type search: dataType={}", dataType);
        return searchService.searchColumnsByDataType(dataType, pageable);
    }

    // ==================== 查询方法 (缓存) ====================

    /**
     * 查询所有表元数据 (带缓存)
     * 用于空关键词搜索时返回所有表
     *
     * @param pageable 分页参数
     * @return 表元数据分页结果
     */
    @Cacheable(value = "metadataQuery", key = "'all:tables:' + #pageable.pageNumber + ':' + #pageable.pageSize",
            unless = "#result == null")
    public Page<MetadataTable> queryAllTables(Pageable pageable) {
        log.debug("Cache miss for query all tables");
        return queryService.queryAllTables(pageable);
    }

    /**
     * 查询指定数据源ID的所有表 (带缓存)
     *
     * @param dataSourceId 数据源ID
     * @param pageable     分页参数
     * @return 表元数据分页结果
     */
    @Cacheable(value = "metadataQuery", key = "'datasource:' + #dataSourceId + ':' + #pageable.pageNumber + ':' + #pageable.pageSize",
            unless = "#result == null")
    public Page<MetadataTable> queryTablesByDataSourceId(Long dataSourceId, Pageable pageable) {
        // 缓存穿透防护: 校验参数
        if (dataSourceId == null || dataSourceId <= 0) {
            log.debug("Invalid data source ID for query, returning empty page");
            return Page.empty(pageable);
        }

        log.debug("Cache miss for data source query: dataSourceId={}", dataSourceId);
        return queryService.queryTablesByDataSourceId(dataSourceId, pageable);
    }

    /**
     * 查询指定表ID的所有列 (带缓存)
     *
     * @param tableId  表ID
     * @param pageable 分页参数
     * @return 列元数据分页结果
     */
    @Cacheable(value = "metadataQuery", key = "'table:' + #tableId + ':columns:' + #pageable.pageNumber + ':' + #pageable.pageSize",
            unless = "#result == null")
    public Page<MetadataColumn> queryColumnsByTableId(Long tableId, Pageable pageable) {
        // 缓存穿透防护: 校验参数
        if (tableId == null || tableId <= 0) {
            log.debug("Invalid table ID for query, returning empty page");
            return Page.empty(pageable);
        }

        log.debug("Cache miss for table columns query: tableId={}", tableId);
        return queryService.queryColumnsByTableId(tableId, pageable);
    }

    // ==================== 缓存管理方法 ====================

    /**
     * 清除所有缓存
     * 用于元数据采集完成后刷新缓存
     */
    @Caching(evict = {
            @CacheEvict(value = "metadataSearch", allEntries = true),
            @CacheEvict(value = "metadataQuery", allEntries = true)
    })
    public void evictAllCaches() {
        log.info("Evicted all metadata caches (search and query)");
    }

    /**
     * 清除搜索缓存
     * 用于搜索索引重建后刷新缓存
     */
    @CacheEvict(value = "metadataSearch", allEntries = true)
    public void evictSearchCache() {
        log.info("Evicted metadata search cache");
    }

    /**
     * 清除查询缓存
     * 用于元数据更新后刷新查询缓存
     */
    @CacheEvict(value = "metadataQuery", allEntries = true)
    public void evictQueryCache() {
        log.info("Evicted metadata query cache");
    }

    /**
     * 清除指定数据源的缓存
     * 用于单个数据源元数据更新后刷新缓存
     *
     * @param dataSourceId 数据源ID
     */
    @CacheEvict(value = "metadataQuery", key = "'datasource:' + #dataSourceId + '*'")
    public void evictDataSourceCache(Long dataSourceId) {
        log.info("Evicted metadata cache for data source: dataSourceId={}", dataSourceId);
    }

    /**
     * 清除指定表的缓存
     * 用于单个表元数据更新后刷新缓存
     *
     * @param tableId 表ID
     */
    @CacheEvict(value = "metadataQuery", key = "'table:' + #tableId + '*'")
    public void evictTableCache(Long tableId) {
        log.info("Evicted metadata cache for table: tableId={}", tableId);
    }
}
